<template>
  <input
    :id="id"
    ref="inputRef"
    :value="modelValue"
    :name="name"
    :disabled="disabled"
    :autocomplete="autocomplete"
    :autofocus="autofocus"
    :type="type"
    :tabindex="tabindex"
    :required="required"
    :placeholder="placeholder"
    :pattern="pattern"
    :minlength="minlength"
    :maxlength="maxlength"
    :min="min"
    :max="max"
    :class="[
      'form-input dark:bg-neutral-700 dark:text-white dark:placeholder-neutral-400',
      {
        'form-input-sm': size === 'sm',
        'form-input-lg': size === 'lg',
        rounded: rounded && size === 'sm',
        'rounded-md': rounded && size !== 'sm' && size !== false,
        'border-neutral-300 dark:border-neutral-500': bordered,
        'border-transparent': !bordered,
      },
    ]"
    @blur="blurHandler"
    @focus="focusHandler"
    @keyup="keyupHandler"
    @keydown="keydownHandler"
    @input="inputHandler"
  />
</template>

<script setup>
import { ref } from 'vue'

defineProps({
  rounded: { default: true, type: Boolean },
  bordered: { default: true, type: Boolean },
  type: { type: String, default: 'text' },
  max: { type: [String, Number], default: undefined },
  min: { type: [String, Number], default: undefined },
  size: {
    type: [String, Boolean],
    default: '',
    validator(value) {
      return ['sm', 'lg', 'md', '', false].includes(value)
    },
  },
  modelValue: [String, Number],
  autocomplete: String,
  maxlength: [String, Number],
  minlength: [String, Number],
  pattern: String,
  placeholder: String,
  id: String,
  name: String,
  disabled: Boolean,
  autofocus: Boolean,
  required: Boolean,
  tabindex: [String, Number],
})

const emit = defineEmits([
  'update:modelValue',
  'focus',
  'blur',
  'input',
  'keyup',
  'keydown',
  'change',
])

const inputRef = ref(null)
const valueWhenFocus = ref(null)

function inputHandler(e) {
  const value = e.target.value

  emit('input', value)
  emit('update:modelValue', value)
}

function blurHandler(e) {
  emit('blur', e)

  if (e.target.value !== valueWhenFocus.value) {
    emit('change', e.target.value)
  }
}

function focusHandler(e) {
  emit('focus', e)

  valueWhenFocus.value = e.target.value
}

function keyupHandler(e) {
  emit('keyup', e)
}

function keydownHandler(e) {
  emit('keydown', e)
}

function blur() {
  inputRef.value.blur()
}

function click() {
  inputRef.value.click()
}

function focus(options) {
  inputRef.value.focus(options)
}

function select() {
  inputRef.value.select()
}

function setRangeText(replacement) {
  inputRef.value.setRangeText(replacement)
}

defineExpose({
  setRangeText,
  select,
  focus,
  click,
  blur,
  inputRef,
})
</script>
